package com.czl.common.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.convert.Convert;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.czl.common.auth.App;
import com.czl.common.auth.CommonLoginInfo;
import com.czl.common.auth.TokenType;
import com.czl.common.auth.bean.AppInfo;
import com.czl.common.util.secret.SecretUtils;
import com.czl.common.redisbase.RedisUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


@Component
public class SimpleTokenUtils {
	@Autowired
	private RedisUtils redisUtilBean;
	private static final Logger LOGGER = LoggerFactory.getLogger(SimpleTokenUtils.class);


	static RedisUtils  redisUtils;

	@PostConstruct
	private void init() {
		SimpleTokenUtils.redisUtils = redisUtilBean;
	}


	//==================================

	public static String getShortTokenByLongToken(String longToken, String appName, AppInfo appInfo) {

		LOGGER.info("getShortTokenByLongToken.begin");
		//检查token有效性 并解析token获取uid
		CommonLoginInfo loginInfo = getLoginInfoByToken(longToken);
		Long uid = loginInfo.getUid();
		if(redisUtils==null){
			redisUtils = SpringUtil.getBean(RedisUtils.class);
		}
		//检查可用短token
//		String shortToken = Convert.toStr(redisUtils.get(longToken));
//
//		LOGGER.info("getShortTokenByLongToken.getShortBy.redis:,{},{}",shortToken,longToken);
//
//		boolean isValid = shortToken!=null&&checkTokenTime(shortToken);
//
//		LOGGER.info("getShortTokenByLongToken.isValid:,{},{},{}",isValid,shortToken,longToken);

		String shortToken=createShortToken( longToken, appName,  uid,   new Date().getTime(), appInfo );
//		//无可用短token 创建短token
//		if(!isValid){
//			shortToken=createShortToken( longToken, appName,  uid,   new Date().getTime(), appInfo );
//		}

		return shortToken;
	}

	public static String createShortToken(String longToken,String appName, Long uid,  Long createTime, AppInfo appInfo)  {
		if(redisUtils==null){
			redisUtils = SpringUtil.getBean(RedisUtils.class);
		}
		String token = createToken(appName, uid, TokenType.SHORT_TOKEN, createTime, appInfo);
		redisUtils.set(longToken,token);
		HashMap<String, Object> tokenMap = new HashMap<>();
		tokenMap.put("longToken",longToken);
		tokenMap.put("shortToken",token);
		redisUtils.set("token_cache_uid_"+appName+uid,JSONUtil.toJsonStr(tokenMap));
		redisUtils.set(token,longToken,60*30);
		return token;
	}

	//检查长token是否存在于缓存
	public static boolean checkLongTokenCache(String longtoken){
		Object o = redisUtils.get(longtoken);
		return o!=null;
	}

	public static boolean clearToken(String appTag,long uid){
		boolean b=false;
		Map<String, String> tokenMap = queryTokenByUid(appTag, uid);
		if(!tokenMap.isEmpty()){
			b=true;
			String longToken = tokenMap.get("longToken");
			String shortToken = tokenMap.get("shortToken");
			redisUtils.del(longToken);
			redisUtils.del(shortToken);
		}
		return b;
	}




	public static Map<String,String> queryTokenByUid(String appTag,long uid) {
		String s = Convert.toStr(redisUtils.get("token_cache_uid_" + appTag + uid), null);
		Map map = new HashMap();
		if (s != null) {
			JSONObject jsonObject = new JSONObject(s);
			map = jsonObject.toBean(Map.class);
		}
		return map;
	};

	public static String queryShortTokenByUid(String appTag,long uid){
		Map<String, String> tokenMap = queryTokenByUid(appTag, uid);
		if(tokenMap==null){
			return null;
		}
		return tokenMap.get("shortToken");
	}

	public static String queryLongTokenByUid(String appTag,long uid){
		Map<String, String> tokenMap = queryTokenByUid(appTag, uid);
		if(tokenMap==null){
			return null;
		}
		return tokenMap.get("longToken");
	}





	public static String createToken(String appName, Long uid, TokenType tokenType, Long createTime, AppInfo appInfo  ){

		if(StringUtils.allIsNotBlank(appName) == false
				|| Tools.toLong(createTime, -1l) <= 0
		){
			return null;
		}


		String extraParamsStr = SecretUtils.toMd5(new Date().getTime()+"base");

		if(TokenType.LONG_TOKEN.equals(tokenType)){
			try {
				extraParamsStr = Base64.encode(appInfo.toJsonString().getBytes("utf-8"));
			} catch (UnsupportedEncodingException e) {
				return null;
			}
		}

		String completeToken = appName +
				"." + createTime+"_"+tokenType.getExpireTime() +
				"." + decToN62(appName,uid) +
				"." + extraParamsStr +
				"." + tokenType.getCode();

		completeToken+="."+MakeTokenSign(completeToken,tokenType);
		return completeToken;
	}

	public static boolean checkToken(String token){
		if(token==null||StringUtils.isBlank(token)){
			return false;
		}
		String[] ss = token.split("\\.");
		String sign=ss[ss.length - 1];
		Integer tokenCode=Convert.toInt(ss[ss.length - 2],null);
		TokenType tokenType = TokenType.FIELDS.get(tokenCode);
		if(tokenType==null)return false;;
		String tempToken = token.replace("."+sign, "");
		return sign.equals(MakeTokenSign(tempToken,tokenType));
	}

	public static boolean checkTokenTime(String token){
		long time= 0;
		long time1 = 0;
		try {
			String times=token.split("\\.")[1];
			String[] s = times.split("_");
			//有效期截止时间  生成时间(毫秒)  + 有效时间(秒)
			time = Tools.toLong(s[0])+(Tools.toLong(s[1])*1000);
			time1 = new Date().getTime();
		} catch (Exception e) {
		    LOGGER.error("checkTokenTime error:"+token,e);
			return false;
		}
		return time<time1;
	}

	public static CommonLoginInfo getLoginInfoByToken(String token){

		if(!checkToken(token)){
			return null;
		}

		CommonLoginInfo cmsLoginInfo = null;
		try {
			String[] strs = token.split("\\.");
			String appTag=strs[0];
			App app = App.TagFIELDS.get(appTag);
			String time=strs[1];
			Long loginTime = Convert.toLong(time.split("_")[0]);
			String uidStr=strs[2];
			String appinfo=strs[3];
			String tokenTypeCode=strs[4];

			TokenType tokenType = TokenType.FIELDS.get(Convert.toInt(tokenTypeCode));
			if(tokenType.equals(TokenType.SHORT_TOKEN)){
				if(redisUtils==null){
					redisUtils = SpringUtil.getBean(RedisUtils.class);
				}
				String longToken = Convert.toStr(redisUtils.get(token),null);

				//长token被清理
				if(longToken==null){
					return null;
				}

				String[] strs2 = longToken.split("\\.");
				appinfo=strs2[3];
			}

			byte[] bytes = Base64.decode(appinfo);
			String s = new String(bytes);
			AppInfo appInfo = JSONUtil.toBean(s , AppInfo.class);
			cmsLoginInfo = new CommonLoginInfo(app,Tools.n62ToLong(uidStr.substring(appTag.length()),null),"1",Convert.toDate(loginTime),appInfo);
		} catch (Exception e) {
			LOGGER.error("getLoginInfoByToken error"+token,e);
		}

		return cmsLoginInfo;
	}

	public static String MakeTokenSign(String token,TokenType tokenType){
		String tokenKey = tokenType.getTokenKey();
		String temp=tokenKey+token.replace(".", "&")+tokenKey;
		String sign = SecretUtils.toSha1(temp);
		return sign;
	}

	private static String decToN62(String appName,Long uid){

		if(StringUtils.isBlank(appName)||uid==null){
			return "";
		}

		String n62OriginalUid = Tools.longToN62(uid, null);
		if(n62OriginalUid == null) {
			return null;
		}

		return appName + n62OriginalUid;
	}

	private static String n62ToDec(String appName,String uid){

		if(StringUtils.isBlank(uid) || uid.length() < 3){
			return null;
		}

		Long originalUid = Tools.n62ToLong(uid.substring(appName.length()), null);
		if(originalUid == null) {
			return null;
		}

		return appName + originalUid.toString();
	}

	public static void main(String[] args) {

//		String s = MakeTokenSign("cms.1599820977183_1800.162lfk4.W10=.1");
//		System.out.println(s);
		boolean b = checkToken("hc.1604303797442_2592000.hc4yfsaPlC.eyJkZXZpY2VJZCI6Ijg2NzcwNzAyNzU0MTIyOCIsImNsaWVudElkIjoiOTkwMiIsImNoYW5uZWxJ\n" +
				"ZCI6IjAwMCIsInZlcnNpb25JZCI6IjMuMC4wIiwibWFjIjoiODQ6QkU6NTI6M0M6ODk6N0EiLCJt\n" +
				"b2RlbCI6Ik1IQS1BTDAwIiwiYnJhbmQiOiJIVUFXRUkiLCJ0cmFjZWlkIjoiODk2N2IzYzdhODk1\n" +
				"MjU3NyIsIm9zdmVyIjoiOSIsImlzSmFpbGJyZWFrIjoiMCIsImlzUGlyYWN5IjoiMCIsImlzU2lt\n" +
				"dWxhdG9yIjoiMCIsImlzS2VybmVsSGlqYWNraW5nIjoiMCIsInNlZWQiOiI4OTY3YjNjN2E4OTUy\n" +
				"NTc3In0=.1.9E1DDDF10ACEFF8D26E4D353555EF4831E703733");
		System.out.println(b);


	}

}
